home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 2 / Atari Mega Archive CD - Volume 2.iso / minix / up1510b.tgz / up1510b / src / commands / login.c < prev    next >
C/C++ Source or Header  |  1990-07-23  |  8KB  |  339 lines

  1. /* login - log into the system            Author: Patric van Kleef */
  2.  
  3. /* Original version by Patrick van Kleef.  History of modifications:
  4.  *
  5.  * Peter S. Housel   Jan. 1988
  6.  *  - Set up $USER, $HOME and $TERM.
  7.  *  - Set signals to SIG_DFL.
  8.  *
  9.  * Terrence W. Holm   June 1988
  10.  *  - Allow a username as an optional argument.
  11.  *  - Time out if a password is not typed within 30 seconds.
  12.  *  - Perform a dummy delay after a bad username is entered.
  13.  *  - Don't allow a login if "/etc/nologin" exists.
  14.  *  - Cause a failure on bad "pw_shell" fields.
  15.  *  - Record the login in "/usr/adm/wtmp".
  16.  *
  17.  * Peter S. Housel   Dec. 1988
  18.  *  - Record the login in "/etc/utmp" also.
  19.  *
  20.  * F. van Kempen     June 1989
  21.  *  - various patches for Minix V1.4a.
  22.  *
  23.  * F. van Kempen     September 1989
  24.  *  - added login-failure administration (new utmp.h needed!).
  25.  *  - support arguments in pw_shell field
  26.  *  - adapted source text to MINIX Style Sheet
  27.  *
  28.  * F. van Kempen     October 1989
  29.  *  - adapted to new utmp database.
  30.  * F. van Kempen,    December 1989
  31.  *  - fixed 'slot' assumption in wtmp()
  32.  *  - fixed all MSS-stuff
  33.  *  - adapted to POSIX (MINIX 1.5)
  34.  * F. van Kempen,    January 1990
  35.  *  - made all 'bad login accounting' optional by "#ifdef BADLOG".
  36.  * F. van Kempen,    Februari 1990
  37.  *  - fixed 'first argument' bug and added some casts.
  38.  *
  39.  * Andy Tanenbaum April 1990
  40.  * - if /bin/sh cannot be located, try /usr/bin/sh
  41.  */
  42.  
  43. #include <sys/types.h>
  44. #include <sys/stat.h>
  45. #include <fcntl.h>
  46. #include <sgtty.h>
  47. #include <signal.h>
  48. #include <string.h>
  49. #include <pwd.h>
  50. #include <unistd.h>
  51. #include <utmp.h>
  52. #include <stdio.h>
  53.  
  54. #define DIGIT                   3
  55. #define MOTD             "/etc/motd"
  56. #define TTY                   "tty?"
  57. #define CONS                  "tty0"
  58.  
  59. static char *Version = "@(#) LOGIN 1.13 (02/10/90)";
  60. int time_out;
  61. char user[32];
  62. char logname[35];
  63. char home[64];
  64. char shell[64];
  65. char *env[] = {
  66.   user,
  67.   logname,
  68.   home,
  69.   shell,
  70.   "TERM=minix",
  71.   NULL
  72. };
  73.  
  74. extern char *crypt();
  75. extern struct passwd *getpwnam();
  76. extern long time();
  77. extern long lseek();
  78. void Time_out();
  79.  
  80. void wtmp(line, user)
  81. char *line;            /* tty device name */
  82. char *user;            /* user name */
  83. {
  84.   /* Make entries in /usr/adm/wtmp and /etc/utmp. */
  85.   struct utmp entry, oldent;
  86.   char *blank = "               ";
  87.   register int fd;
  88.   register char *sp;
  89.   int lineno;
  90.   extern long time();
  91.  
  92.   /* Strip off the /dev part of the TTY name. */
  93.   sp = strrchr(line, '/');
  94.   if (sp == NULL)
  95.     sp = line;
  96.   else
  97.     sp++;
  98.  
  99.   /* First, read the current UTMP entry. we need some of its
  100.    * parameters! (like PID, ID etc...). */
  101.   if ((fd = open(UTMP, O_RDONLY)) < 0) return;
  102.   lineno = 0;
  103.   while (read(fd, (char *) &oldent, sizeof(struct utmp))
  104.                     == sizeof(struct utmp)) {
  105.     if (oldent.ut_pid == getpid()) break;
  106.     lineno++;
  107.   }
  108.   lineno *= sizeof(struct utmp);
  109.  
  110.   if (lseek(fd, (long) lineno, SEEK_SET) >= 0) {
  111.     read(fd, (char *) &oldent, sizeof(struct utmp));
  112.   }
  113.   close(fd);
  114.  
  115.   /* Clear out the new string fields. */
  116.   strncpy(entry.ut_user, blank, sizeof(entry.ut_user));
  117.   strncpy(entry.ut_id, blank, sizeof(entry.ut_id));
  118.   strncpy(entry.ut_line, blank, sizeof(entry.ut_line));
  119.  
  120.   /* Enter new string fields. */
  121.   strncpy(entry.ut_user, user, sizeof(entry.ut_user));
  122.   strncpy(entry.ut_id, oldent.ut_id, sizeof(entry.ut_id));
  123.   strncpy(entry.ut_line, sp, sizeof(entry.ut_line));
  124.  
  125.   /* Copy old numeric fields. */
  126.   entry.ut_pid = oldent.ut_pid;
  127.  
  128.   /* Change new numeric fields. */
  129.   entry.ut_type = USER_PROCESS;    /* we are past login... */
  130.   time(&(entry.ut_time));
  131.  
  132.   /* Write a WTMP record. */
  133.   if ((fd = open(WTMP, O_WRONLY)) > 0) {
  134.     if (lseek(fd, 0L, SEEK_END) >= 0L) {
  135.         write(fd, (char *) &entry, sizeof(struct utmp));
  136.     }
  137.     close(fd);
  138.   }
  139.   /* Rewrite the UTMP entry. */
  140.   if ((fd = open(UTMP, O_WRONLY)) > 0) {
  141.     if (lseek(fd, (long) lineno, SEEK_SET) >= 0) {
  142.         write(fd, (char *) &entry, sizeof(struct utmp));
  143.     }
  144.     close(fd);
  145.   }
  146. }
  147.  
  148.  
  149. #ifdef BADLOG
  150. void addlog(nam, pwd, tty)
  151. char *nam;            /* name of attempting user */
  152. char *pwd;            /* attempted password */
  153. char *tty;            /* name of terminal line */
  154. {
  155. /* Register a failed login if the logfile exists. */
  156.   struct utmp entry;
  157.   int fd;
  158.  
  159.   strncpy(entry.ut_name, nam, sizeof(entry.ut_name));
  160.   strncpy(entry.ut_line, tty, sizeof(entry.ut_line));
  161.   entry.ut_time = time((time_t *)0);
  162.  
  163.   if ((fd = open(BTMP, O_WRONLY)) < 0) return;
  164.  
  165.   if (lseek(fd, 0L, SEEK_END) >= 0L) {
  166.     /* Append the entry to the btmp file. */
  167.     write(fd, (char *) &entry, sizeof(struct utmp));
  168.   }
  169.   close(fd);
  170. }
  171. #endif /* BADLOG */
  172.  
  173.  
  174. void show_file(nam)
  175. char *nam;
  176. {
  177. /* Read a textfile and show it on the desired terminal. */
  178.   register int fd, len;
  179.   char buf[80];
  180.  
  181.   if ((fd = open(nam, O_RDONLY)) > 0) {
  182.     len = 1;
  183.     while (len > 0) {
  184.         len = read(fd, buf, 80);
  185.         write(1, buf, len);
  186.     }
  187.     close(fd);
  188.   }
  189. }
  190.  
  191.  
  192. int main(argc, argv)
  193. int argc;
  194. char *argv[];
  195. {
  196.   char name[30];
  197.   char password[30];
  198.   char ttyname[16];
  199.   int bad, n, ttynr, ap;
  200.   struct sgttyb args;
  201.   struct passwd *pwd;
  202.   struct stat statbuf;
  203.   char *bp, *argx[8];        /* pw_shell arguments */
  204.   char *sh = "/bin/sh";        /* sh/pw_shell field value */
  205.   char *sh2= "/usr/bin/sh";    /* other possibility */
  206.  
  207.   /* Reset some of the line parameters in case they have been mashed. */
  208.   if (ioctl(0, TIOCGETP, &args) < 0) exit(1);
  209. #ifdef NOGETTY
  210.   args.sg_kill = '\030';    /* CTRL-X */
  211.   args.sg_erase = '\b';
  212.   args.sg_flags |= (XTABS | CRMOD | ECHO);
  213.   ioctl(0, TIOCSETP, &args);
  214. #endif /* NOGETTY */
  215.  
  216.   /* Look up /dev/tty number. */
  217.   fstat(0, &statbuf);
  218.   ttynr = statbuf.st_rdev & 0377;
  219.   if (ttynr == 0)
  220.     strcpy(ttyname, CONS);    /* system console */
  221.   else {
  222.     strcpy(ttyname, TTY);
  223.     ttyname[DIGIT] = '0' + ttynr;
  224.   }
  225.  
  226.   /* Get login name and passwd. */
  227.   for (;;) {
  228.     bad = 0;
  229.  
  230.     if (argc > 1) {
  231.         strcpy(name, argv[1]);
  232.         argc = 1;
  233.     } else {
  234.         do {
  235.             write(1, "login: ", 7);
  236.             n = read(0, name, 30);
  237.         } while (n < 2);
  238.         name[n - 1] = 0;
  239.     }
  240.  
  241.     /* Look up login/passwd. */
  242.     if ((pwd = getpwnam(name)) == (struct passwd *) NULL) bad++;
  243.  
  244.     /* If login name wrong or password exists, ask for pw. */
  245.     if (bad || strlen(pwd->pw_passwd) != 0) {
  246.         args.sg_flags &= ~ECHO;
  247.         ioctl(0, TIOCSETP, &args);
  248.         write(1, "Password: ", 10);
  249.  
  250.         time_out = 0;
  251.         signal(SIGALRM, Time_out);
  252.         alarm(30);
  253.  
  254.         n = read(0, password, 30);
  255.  
  256.         alarm(0);
  257.         if (time_out) {
  258.             n = 1;
  259.             bad++;
  260.         }
  261.         password[n - 1] = 0;
  262.         write(1, "\n", 1);
  263.         args.sg_flags |= ECHO;
  264.         ioctl(0, TIOCSETP, &args);
  265.  
  266.         if (bad && crypt(password, "aaaa") ||
  267.             strcmp(pwd->pw_passwd, crypt(password, pwd->pw_passwd))) {
  268. #ifdef BADLOG
  269.             addlog(name, password, ttyname);
  270. #endif /* BADLOG */
  271.             write(1, "Login incorrect\n", 16);
  272.             continue;
  273.         }
  274.     }
  275.     /* Check if the system is going down  */
  276.     if (access("/etc/nologin", 0) == 0 && strcmp(name, "root") != 0) {
  277.         write(1, "System going down\n\n", 19);
  278.         continue;
  279.     }
  280.     /* Write login record to /usr/adm/wtmp and /etc/utmp */
  281.     wtmp(ttyname, name);
  282.  
  283.     /* Create the argv[] array from the pw_shell field. */
  284.     ap = 0;
  285.     argx[ap++] = "-";    /* most shells need it for their .profile */
  286.     if (pwd->pw_shell[0]) {
  287.         sh = pwd->pw_shell;
  288.         bp = sh;
  289.         while (*bp) {
  290.             while (*bp && *bp != ' ' && *bp != '\t') bp++;
  291.             if (*bp == ' ' || *bp == '\t') {
  292.                 *bp++ = '\0';    /* mark end of string */
  293.                 argx[ap++] = bp;
  294.             }
  295.         }
  296.     } else
  297.     argx[ap] = (char *) NULL;
  298.  
  299.     /* Set the environment */
  300.     strcpy(user, "USER=");
  301.     strcat(user, name);
  302.     strcpy(logname, "LOGNAME=");
  303.     strcat(logname, name);
  304.     strcpy(home, "HOME=");
  305.     strcat(home, pwd->pw_dir);
  306.     strcpy(shell, "SHELL=");
  307.     strcat(shell, sh);
  308.  
  309.     chdir(pwd->pw_dir);
  310.  
  311.     /* Reset signals to default values. */
  312.     for (n = 1; n <= _NSIG; ++n) signal(n, SIG_DFL);
  313.  
  314.     /* Show the message-of-the-day. */
  315.     show_file(MOTD);
  316.  
  317.     /* Assign the terminal to this user. */
  318.     strcpy(name, "/dev/");
  319.     strcat(name, ttyname);
  320.     chown(name, pwd->pw_uid, pwd->pw_gid);
  321.  
  322.     setgid(pwd->pw_gid);
  323.     setuid(pwd->pw_uid);
  324.     execve(sh, argx, env);
  325.     execve(sh2, argx, env);        /* if /bin/sh absent, try /usr/bin/sh*/
  326.  
  327.     write(1, "exec failure\n", 13);
  328.     exit(1);
  329.   }
  330. }
  331.  
  332.  
  333. void Time_out()
  334. {
  335.    time_out = 1;
  336. }
  337.  
  338.  
  339.